<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>3D Generator Test</title>
  <script src="../_libs/raphael-min.2.0.1.js"></script>
  <script src="../_libs/Three.js"></script>
  <!--
  <script src="../../src/_extras/OpenBabel/openbabel.js.O1"></script>
  -->


  <script src="../../src/kekule.js?min=false&modules=calculation,chemWidget,openbabel"></script>

  <!--
  <script src="../../src/_compressed/kekule.js?min=true&modules=calculation,chemWidget,openbabel"></script>
  -->
  <!--
  <script src="../../release/kekule.js?min=true&modules=calculation,chemWidget,openbabel"></script>
  -->

  <!--
  <script src="../../src/_compressed/kekule.min.js"></script>
  -->
  <!--
  <link rel="stylesheet" type="text/css" href="../../src/widgets/themes/default/default.css" />
  <link rel="stylesheet" type="text/css" href="../../src/widgets/themes/default/defaultColor.css" />
  <link rel="stylesheet" type="text/css" href="../../src/widgets/themes/default/chemWidget.css" />
  <link rel="stylesheet" type="text/css" href="../../src/widgets/themes/default/chemWidgetColor.css" />
  -->
  <link rel="stylesheet" type="text/css" href="../../src/widgets/themes/default/kekule.css" />

<script name="(2E,4E,6E,8E)-deca-2,4,6,8-tetraene" id="molSrc" type="chemical/x-mdl-molfile">
Untitled Document-1
  ChemDraw10021112262D

 10  9  0  0  0  0  0  0  0  0999 V2000
   -3.2151    0.2062    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
   -2.5006   -0.2062    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
   -1.7862    0.2062    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
   -1.0717   -0.2062    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
   -0.3572    0.2062    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    0.3572   -0.2062    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    1.0717    0.2062    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    1.7862   -0.2062    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    2.5006    0.2062    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    3.2151   -0.2062    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
  1  2  1  0
  2  3  2  0
  3  4  1  0
  4  5  2  0
  5  6  1  0
  6  7  2  0
  7  8  1  0
  8  9  2  0
  9 10  1  0
M  END
</script>
  <script name="carboxyl" id="carboxyl" type="chemical/x-kekule-json">
	  {"id":"m1","coordPos2D":0,"coordPos3D":0,"renderOptions":{"expanded":true,"__type__":"object"},"coord2D":{"x":3.050666666666622,"y":2.2239999999998616,"__type__":"object"},"charge":0,"parity":null,"ctab":{"nodes":[{"__type__":"Kekule.Atom","id":"a1","coordPos2D":0,"coordPos3D":0,"coord2D":{"x":11.349333333333332,"y":43.775999999999996,"__type__":"object"},"charge":0,"parity":null,"isotopeId":"C"},{"__type__":"Kekule.Atom","id":"a3","coordPos2D":0,"coordPos3D":0,"coord2D":{"x":10.656513010305785,"y":44.176,"__type__":"object"},"charge":0,"parity":null,"isotopeId":"O"},{"__type__":"Kekule.Atom","id":"a2","coordPos2D":0,"coordPos3D":0,"coord2D":{"x":12.042153656360883,"y":44.17599999999999,"__type__":"object"},"charge":0,"parity":null,"isotopeId":"O"},{"__type__":"Kekule.Atom","id":"a4","coordPos2D":0,"coordPos3D":0,"coord2D":{"x":9.963692687278233,"y":43.77600000000001,"__type__":"object"},"charge":0,"parity":null,"isotopeId":"H"}],"anchorNodes":[],"connectors":[{"__type__":"Kekule.Bond","id":"b2","coordPos2D":0,"coordPos3D":0,"parity":null,"bondType":"covalent","bondOrder":1,"electronCount":2,"isInAromaticRing":false,"connectedObjs":[0,1]},{"__type__":"Kekule.Bond","id":"b1","coordPos2D":0,"coordPos3D":0,"bondType":"covalent","bondOrder":2,"electronCount":4,"isInAromaticRing":false,"connectedObjs":[0,2]},{"__type__":"Kekule.Bond","id":"b3","coordPos2D":0,"coordPos3D":0,"parity":null,"bondType":"covalent","bondOrder":1,"electronCount":2,"isInAromaticRing":false,"connectedObjs":[1,3]}],"__type__":"Kekule.StructureConnectionTable"},"__type__":"Kekule.Molecule"}
  </script>
  <script name="sulfonic " id="sulfonic" type="chemical/x-kekule-json">
    {"id":"m1","coordPos2D":0,"coordPos3D":0,"renderOptions":{"expanded":true,"__type__":"object"},"coord2D":{"x":1.4720000000000262,"y":1.456000000000067,"__type__":"object"},"charge":0,"parity":null,"ctab":{"nodes":[{"__type__":"Kekule.Atom","id":"a1","coordPos2D":0,"coordPos3D":0,"coord2D":{"x":12.927999999999999,"y":44.544,"__type__":"object"},"charge":0,"parity":null,"isotopeId":"S"},{"__type__":"Kekule.Atom","id":"a4","coordPos2D":0,"coordPos3D":0,"coord2D":{"x":12.927999999999999,"y":43.744,"__type__":"object"},"charge":0,"parity":null,"isotopeId":"O"},{"__type__":"Kekule.Atom","id":"a2","coordPos2D":0,"coordPos3D":0,"coord2D":{"x":13.620820323027548,"y":44.944,"__type__":"object"},"charge":0,"parity":null,"isotopeId":"O"},{"__type__":"Kekule.Atom","id":"a3","coordPos2D":0,"coordPos3D":0,"coord2D":{"x":12.235179676972443,"y":44.94399999999999,"__type__":"object"},"charge":0,"parity":null,"isotopeId":"O"},{"__type__":"Kekule.Atom","id":"a5","coordPos2D":0,"coordPos3D":0,"coord2D":{"x":13.62082032302755,"y":43.344,"__type__":"object"},"charge":0,"parity":null,"isotopeId":"H"}],"anchorNodes":[],"connectors":[{"__type__":"Kekule.Bond","id":"b3","coordPos2D":0,"coordPos3D":0,"parity":null,"bondType":"covalent","bondOrder":1,"electronCount":2,"isInAromaticRing":false,"connectedObjs":[0,1]},{"__type__":"Kekule.Bond","id":"b1","coordPos2D":0,"coordPos3D":0,"bondType":"covalent","bondOrder":2,"electronCount":4,"isInAromaticRing":false,"connectedObjs":[0,2]},{"__type__":"Kekule.Bond","id":"b2","coordPos2D":0,"coordPos3D":0,"bondType":"covalent","bondOrder":2,"electronCount":4,"isInAromaticRing":false,"connectedObjs":[0,3]},{"__type__":"Kekule.Bond","id":"b4","coordPos2D":0,"coordPos3D":0,"parity":null,"bondType":"covalent","bondOrder":1,"electronCount":2,"isInAromaticRing":false,"connectedObjs":[1,4]}],"__type__":"Kekule.StructureConnectionTable"},"__type__":"Kekule.Molecule"}
  </script>

  <script>
    var chemEditor;
    var chemEditorUi;
    var viewer;
    var calculator;
    var acidicGroups = [];
    var acidicReplacementGroups = [];
    var REPLACE_SYMBOL = 'F';

    function getCurrMol()
    {
      //return chemEditor.getChemSpace().getChildAt(0);
      return Kekule.ChemStructureUtils.getTotalStructFragment(chemEditor.getChemSpace());
    }

    function fillAcidicGroupList()
    {
    	var ids = ['carboxyl', 'sulfonic'];
    	for (var i = 0, l = ids.length; i < l; ++i)
      {
        Kekule.IO.loadResourceData('url(#' + ids[i] + ')', function(chemObj, success){
        	if (success && chemObj)
	        {
		        acidicGroups.push(chemObj);
		        var replaced = chemObj.clone();
		        replaceAcidicHydrogenInAcidicGroup(replaced, null, REPLACE_SYMBOL);
		        acidicReplacementGroups.push(replaced);
	        }
        });
      }
    }
    function replaceAcidicHydrogenInAcidicGroup(mol, groupObjs, replacementAtomSymbol)
    {
    	if (!groupObjs)
    		groupObjs = mol.getNodes();
    	for (var i = 0, l = groupObjs.length; i < l; ++i)
      {
      	var obj = groupObjs[i];
      	var node = (obj instanceof Kekule.Atom)? obj: null;
      	if (node)
	      {
	      	var atomOxygen;
		      if (node.getSymbol() === 'H')  // explicit H
		      {
			      node.setSymbol(replacementAtomSymbol);  // replace directly
            atomOxygen = node.getLinkedChemNodes(true)[0];
		      }
		      else if (node.getSymbol() === 'O')
		      {
			      var explicitHCount = node.getHydrogenCount(false); // do not includ explicit bonded H
			      if (explicitHCount === 1)
			      {
				      var newAtom = mol.appendAtom(replacementAtomSymbol);
				      mol.appendBond([node, newAtom], Kekule.BondOrder.SINGLE);
				      atomOxygen = node;
			      }
		      }
		      if (atomOxygen)
          {
          	atomOxygen.setMassNumber(19);  // set to a extraordinary mass number, avoid to be searched again
            break;
          }
	      }
      }
    }
    function replaceBackAcidicHydrogenInAcidicGroup(mol, groupObjs, replacementAtomSymbol)
    {
    	for (var i = 0, l = groupObjs.length; i < l; ++i)
      {
      	var obj = groupObjs[i];
      	if (obj instanceof Kekule.Atom)
	      {
		      if (obj.getSymbol() === replacementAtomSymbol)
			      obj.setSymbol('H');
		      else if (obj.getSymbol() === 'O' && obj.getMassNumber() === 19)
		      	obj.setMassNumber(null);
	      }
      }
    	return mol;
    }

    function replaceAcidicHydrogens(mol, acidicGroup, replacementAtomSymbol)
    {
    	var result = mol.clone();
      var searchResult = result.search(acidicGroup, {level: Kekule.StructureComparationLevel.CONSTITUTION, mass: true});
      while (searchResult)
      {
	      replaceAcidicHydrogenInAcidicGroup(result, searchResult, replacementAtomSymbol);
	      searchResult = result.search(acidicGroup, {level: Kekule.StructureComparationLevel.CONSTITUTION, mass: true});
      }
      return result;
    }
    function replaceBackAcidicHydrogens(mol, repalcedAcidicGroup, replacementAtomSymbol)
    {
    	var result = mol.clone(true);
	    var testMol = mol.clone(true);  // clone with id
	    var searchResult = testMol.search(repalcedAcidicGroup, {level: Kekule.StructureComparationLevel.CONSTITUTION, mass: true});
	    while (searchResult)
	    {
	    	// map ids in testMol to result
        var groupMembers = [];
        for (var i = 0, l = searchResult.length; i < l; ++i)
        {
        	var obj = getChildById(result, searchResult[i].getId());
        	if (obj)
        		groupMembers.push(obj);
        }
		    replaceBackAcidicHydrogenInAcidicGroup(testMol, searchResult, replacementAtomSymbol);
		    replaceBackAcidicHydrogenInAcidicGroup(result, groupMembers, replacementAtomSymbol);
		    searchResult = testMol.search(repalcedAcidicGroup, {level: Kekule.StructureComparationLevel.CONSTITUTION, mass: true});
	    }
	    return result;
    }
    function getChildById(mol, id)
    {
    	for (var i = 0, l = mol.getChildCount(); i < l; ++i)
      {
      	var obj = mol.getChildAt(i);
      	if (obj.getId() === id)
      		return obj;
      }
    	return null;
    }

    function prepareSourceMol(mol)
    {
    	var result = mol;
    	for (var i = 0, l = acidicGroups.length; i < l; ++i)
      {
	      result = replaceAcidicHydrogens(result, acidicGroups[i], REPLACE_SYMBOL);
      }
    	//console.log('after prepared', Kekule.IO.saveFormatData(result, 'smi'));
    	return result;
    }
    function prepareOutputMol(mol)
    {
	    var result = mol.clone();
      // assign id to result nodes
      for (var i = 0, l = result.getNodeCount(); i < l; ++i)
      {
      	var node = result.getNodeAt(i);
      	node.setId('n' + i);
      }
	    //console.log('before prepared', Kekule.IO.saveFormatData(result, 'smi'));
	    for (var i = 0, l = acidicReplacementGroups.length; i < l; ++i)
	    {
		    result = replaceBackAcidicHydrogens(result, acidicReplacementGroups[i], REPLACE_SYMBOL);
	    }
	    //console.log('after prepared', Kekule.IO.saveFormatData(result, 'smi'));
	    return result;
    }

    function generate3D()
    {
      var sync = Kekule.Widget.getWidgetById('checkBoxSync').getChecked();
      if (sync)
        return generate3DSync();
      else
        return generate3DAsync();
    }

    function generate3DAsync()
    {
      var mol = getCurrMol();
      mol = prepareSourceMol(mol);
      var msgs = [];
      /*
      var generator = new Kekule.Calculator.ObStructure3DGenerator();
      generator.setSourceMol(mol);
      generator.execute(function(){
        var mol3D = generator.getGeneratedMol();
        console.log(mol3D);
        viewer.setChemObj(mol3D);
      });
      */
      var useFFCalc = Kekule.Widget.getWidgetById('checkBoxUseFF').getChecked();
      var opSpeed = Kekule.Widget.getWidgetById('selSpeed').getValue();

      var tickStart = Date.now();
      calculator = Kekule.Calculator.generate3D(mol, {'applyFFCalc': useFFCalc, forceField: '', 'speed': opSpeed},
        function(generatedMol){
          var tickEnd = Date.now();
          var duration = tickEnd - tickStart;
          document.getElementById('labelDuration').innerHTML = 'Calculated in ' + duration + ' ms';

          console.log(generatedMol);

          var newMol = prepareOutputMol(generatedMol);
          viewer.setChemObj(newMol);

          //viewer.setChemObj(generatedMol);
        },
        function(err)
        {
          if (err)
            Kekule.error(err);
        },
        function (msgData)
        {
          if (msgData.type === 'print' || msgData.type === 'printErr')
          {
            msgs.push('[' + (new Date()).toLocaleTimeString() + '][' + msgData.type + ']' + msgData.data);
            Kekule.Widget.getWidgetById('memoLog').setValue(msgs.join('\n'));
          }
        }
      );
    }
    function terminate()
    {
      if (calculator)
        calculator.halt();
    }

    function generate3DSync()
    {
      var mol = getCurrMol();
      mol = prepareSourceMol(mol);
      var msgs = [];

      var useFFCalc = Kekule.Widget.getWidgetById('checkBoxUseFF').getChecked();
      var opSpeed = Kekule.Widget.getWidgetById('selSpeed').getValue();

      var generator = new Kekule.Calculator.ObStructure3DGenerator();
      generator.setSourceMol(mol);
      generator.setOptions({'applyFFCalc': useFFCalc, 'speed': opSpeed});
      generator.executeSync(function(){
        var mol3D = generator.getGeneratedMol();
        console.log(mol3D);
        viewer.setChemObj(mol3D);
      });
    }

    function init()
    {
	    fillAcidicGroupList();

      var elem = document.getElementById('chemEditorUi');
      chemEditor = new Kekule.Editor.ChemSpaceEditor(document, null, Kekule.Render.RendererType.R2D);
      chemEditorUi = new Kekule.Editor.Composer(elem, chemEditor);
      viewer = Kekule.Widget.getWidgetById('chemViewer');

      var toolButtons = chemEditorUi.getCommonToolButtons() || chemEditorUi.getDefaultCommonToolBarButtons();
      toolButtons.push({
        'text': 'Generate 3D', 'hint': 'Generate 3D structure', 'showText': true, 'showGlyph': false, 'cssText': 'background-color:yellow;width:auto',
        '#execute': generate3D
      });
      chemEditorUi.setCommonToolButtons(toolButtons);
    }
  </script>
</head>
<body onload="init()">
<div id="calcPanel">
  <button type="button" onclick="generate3D()">Generate</button>
  <button type="button" onclick="terminate()">Terminate</button>
  <span id="checkBoxSync" data-widget="Kekule.Widget.CheckBox" data-text="Sync"></span>
  <span id="checkBoxUseFF" data-widget="Kekule.Widget.CheckBox" data-text="Use FF Calc"></span>
  <label>Gen3D Operation Speed
    <select id="selSpeed" data-widget="Kekule.Widget.SelectBox" data-items='[{"value":1},{"value":2},{"value":3,"selected":true},{"value":4},{"value":5},{"value":6}]'></select>
  </label>
  <label id="labelDuration"></label>
</div>
<div id="chemEditorUi" style="width:600px;height:400px;float:left" data-chem-obj="url(#molSrc)"></div>
<div id="chemViewer" style="width:500px;height:400px;float:left" data-widget="Kekule.ChemWidget.Viewer3D" data-predefined-setting="fullFunc"></div>
<div id="logPanel">
  <div id="memoLog" style="width:100em;height:40em" data-widget="Kekule.Widget.TextEditor"></div>
</div>

</body>
</html>